/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.util;

import java.net.Socket;
import java.net.SocketException;

import org.zhiqim.kernel.annotation.AnAlias;

/**
 * Socket相关工具类
 *
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 */
@AnAlias("Sockets")
public class Sockets
{
    /**
     * 设置Socket参数
     * 
     * @param socket        Socket
     * @param tcpNoDelay    Enable/disable TCP_NODELAY是否立即响应，即非延迟,不采用Nagle算法
     * @param soTimeoutMs   Enable/disable SO_TIMEOUT 读流数据超时时长，单位毫秒，0表示一直阻塞不超时，建议>0
     * @param soLingerS     Enable/disable SO_LINGER 关闭Socket等待时长，即TIME_WAIT时长，单位秒，Java默认最大65535，实际还受制于各系统实现的最大值，系统默认2MLS即4分钟(MLS:Maximum Segment Lifetime英文的缩写,中文可以译为报文最大生存时间,默认2分钟)
     */
    public static Socket setOption(Socket socket, boolean tcpNoDelay, int soTimeoutMs, int soLingerS)
    {
        try
        {
            socket.setTcpNoDelay(tcpNoDelay);
            if (soTimeoutMs >= 0)
            {//读数据流超时时间
                socket.setSoTimeout(soTimeoutMs);
            }
            if (soLingerS >= 0)
            {//=0表示立即关闭返回并放弃后面的数据发送，>0表示阻塞返回等待指定的秒数发送，如果完成关闭，未发送完关闭放弃后面数据（比=0和<0方案更合理些，可以根据业务来设置等待时长）
                socket.setSoLinger(true, soLingerS);
            }
            else
            {//<0表示立即返回，由系统等待数据发送完毕后关闭（通常会被操作系统强制设置等待秒数，如linux是30秒，windows是240秒）
                socket.setSoLinger(false, -1);
            }
            
            return socket;
        }
        catch (SocketException e)
        {
            throw Asserts.exception("Sockets.setOption{soTimeoutMs:"+soTimeoutMs+",soLingerS:"+soLingerS+"},SocketException");
        }
    }
    
    /**
     * 设置Socket参数
     * 
     * @param socket        Socket
     * @param tcpNoDelay    Enable/disable TCP_NODELAY 是否立即响应，即非延迟,不采用Nagle算法
     * @param soTimeoutMs   Enable/disable SO_TIMEOUT 读流数据超时时长，单位毫秒，0表示一直阻塞不超时，建议>0
     * @param soLingerS     Enable/disable SO_LINGER 关闭Socket等待时长，即TIME_WAIT时长，单位秒，JAVA默认最大65535，实际还受制于各系统实现的最大值，系统默认2MLS即4分钟(MLS:Maximum Segment Lifetime英文的缩写,中文可以译为报文最大生存时间,默认2分钟)
     * @param keepAlive     Enable/disable SO_KEEPALIVE 是否检查连接有效性，默认2小时检查基本上没意思，每请求连接时可设置为false，超长连接时可设置为true
     */
    public static Socket setOption(Socket socket, boolean tcpNoDelay, int soTimeoutMs, int soLingerS, boolean keepAlive)
    {
        setOption(socket, tcpNoDelay, soTimeoutMs, soLingerS);
        
        try
        {
            socket.setKeepAlive(keepAlive);
            return socket;
        }
        catch (SocketException e)
        {
            throw Asserts.exception("Sockets.setOption{soTimeoutMs:"+soTimeoutMs+",soLingerS:"+soLingerS+"},SocketException");
        }
    }
}
